//---------------------------------------------------------------------
//  This file is part of the Windows Workflow Foundation SDK Code Samples.
// 
//  Copyright (C) Microsoft Corporation.  All rights reserved.
// 
//This source code is intended only as a supplement to Microsoft
//Development Tools and/or on-line documentation.  See these other
//materials for detailed information regarding Microsoft code samples.
// 
//THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//---------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime.Tracking;

namespace DP.Sharepoint.Workflow.Tests.ForTesting
{
    public class TraceTrackingChannel : TrackingChannel
    {
        const string DTFORMAT = "yyyy-MM-dd hh:mm";
        private readonly TrackingParameters parameters;

        protected TraceTrackingChannel()
        {
        }

        public TraceTrackingChannel(TrackingParameters parameters)
        {
            this.parameters = parameters;
        }

        // Send() is called by Tracking runtime to send various tracking records
        public TrackingParameters Parameters
        {
            get { return parameters; }
        }

        protected override void Send(TrackingRecord record)
        {
            // filter on record type
            if (record is WorkflowTrackingRecord)
            {
                WriteWorkflowTrackingRecord((WorkflowTrackingRecord) record);
            }
            if (record is ActivityTrackingRecord)
            {
                WriteActivityTrackingRecord((ActivityTrackingRecord) record);
            }
            if (record is UserTrackingRecord)
            {
                WriteUserTrackingRecord((UserTrackingRecord) record);
            }
        }

        // InstanceCompletedOrTerminated() is called by Tracking runtime to indicate that the Workflow instance finished running
        protected override void InstanceCompletedOrTerminated()
        {
            WriteTitle("Workflow Instance Completed or Terminated", DateTime.Now);
        }

        private static void WriteTitle(string title, DateTime eventTime)
        {
            Trace.Write(string.Format("**{0}** EventDateTime: {1} ", title, eventTime.ToString(DTFORMAT)));
        }

        private static void WriteWorkflowTrackingRecord(WorkflowTrackingRecord workflowTrackingRecord)
        {
            WriteTitle("Workflow", workflowTrackingRecord.EventDateTime);
            Trace.WriteLine(string.Format("\tStatus {0}", workflowTrackingRecord.TrackingWorkflowEvent));
        }

        private static void WriteActivityTrackingRecord(ActivityTrackingRecord activityTrackingRecord)
        {
            WriteTitle("Activity", activityTrackingRecord.EventDateTime);
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("QualifiedName: {0}\t", activityTrackingRecord.QualifiedName);
            sb.AppendFormat("Type: {0}\t", activityTrackingRecord.ActivityType);
            sb.AppendFormat("Status: {0}\t", activityTrackingRecord.ExecutionStatus);
            Trace.WriteLine(sb.ToString());
        }

        private static void WriteUserTrackingRecord(UserTrackingRecord userTrackingRecord)
        {
            WriteTitle("User",userTrackingRecord.EventDateTime);
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("QualifiedName: {0}\t", userTrackingRecord.QualifiedName);
            sb.AppendFormat("ActivityType: {0}\t", userTrackingRecord.ActivityType.FullName);
            sb.AppendFormat("Args: {0}\t", userTrackingRecord.UserData);
            Trace.WriteLine(sb.ToString());
        }
    }

    public class TraceTrackingService : TrackingService
    {
        protected override bool TryGetProfile(Type workflowType, out TrackingProfile profile)
        {
            //Depending on the workflowType, service can return different tracking profiles
            //In this sample we're returning the same profile for all running types
            profile = GetProfile();
            return true;
        }

        protected override TrackingProfile GetProfile(Guid workflowInstanceId)
        {
            // Does not support reloading/instance profiles
            throw new NotImplementedException("The method or operation is not implemented.");
        }

        protected override TrackingProfile GetProfile(Type workflowType, Version profileVersionId)
        {
            // Return the version of the tracking profile that runtime requests (profileVersionId)
            return GetProfile();
        }

        protected override bool TryReloadProfile(Type workflowType, Guid workflowInstanceId, out TrackingProfile profile)
        {
            // Returning false to indicate there is no new profiles
            profile = null;
            return false;
        }

        protected override TrackingChannel GetTrackingChannel(TrackingParameters parameters)
        {
            //return a tracking channel to receive runtime events
            return new TraceTrackingChannel(parameters);
        }

        // Profile creation
        private static TrackingProfile GetProfile()
        {
            // Create a Tracking Profile
            TrackingProfile profile = new TrackingProfile();
            profile.Version = new Version("3.0.0");

            // Add a TrackPoint to cover all activity status events
            ActivityTrackPoint activityTrackPoint = new ActivityTrackPoint();
            ActivityTrackingLocation activityLocation = new ActivityTrackingLocation(typeof (Activity));
            activityLocation.MatchDerivedTypes = true;

            IEnumerable<ActivityExecutionStatus> statuses =
                Enum.GetValues(typeof (ActivityExecutionStatus)) as IEnumerable<ActivityExecutionStatus>;
            if (statuses != null)
                foreach (ActivityExecutionStatus status in statuses)
                {
                    activityLocation.ExecutionStatusEvents.Add(status);
                }

            activityTrackPoint.MatchingLocations.Add(activityLocation);
            profile.ActivityTrackPoints.Add(activityTrackPoint);

            // Add a TrackPoint to cover all workflow status events
            WorkflowTrackPoint workflowTrackPoint = new WorkflowTrackPoint();
            workflowTrackPoint.MatchingLocation = new WorkflowTrackingLocation();
            foreach (TrackingWorkflowEvent workflowEvent in Enum.GetValues(typeof (TrackingWorkflowEvent)))
            {
                workflowTrackPoint.MatchingLocation.Events.Add(workflowEvent);
            }
            profile.WorkflowTrackPoints.Add(workflowTrackPoint);

            // Add a TrackPoint to cover all user track points
            UserTrackPoint userTrackPoint = new UserTrackPoint();
            UserTrackingLocation userLocation = new UserTrackingLocation();
            userLocation.ActivityType = typeof (Activity);
            userLocation.MatchDerivedActivityTypes = true;
            userLocation.ArgumentType = typeof (object);
            userLocation.MatchDerivedArgumentTypes = true;
            userTrackPoint.MatchingLocations.Add(userLocation);
            profile.UserTrackPoints.Add(userTrackPoint);

            return profile;
        }
    }
}